#ifndef AFCORE_COMMON_LOG_ASYNC_ASYNC_THREAD_POOL_
#define AFCORE_COMMON_LOG_ASYNC_ASYNC_THREAD_POOL_

#include <thread>
#include <functional>

#include "logcommon.h"
#include "log_msg_buf.h"
#include "nocopyable.h"
#include "mpmc_queue.h"
#include "async_logger.h"

namespace afcore {

/// @brief  日志
namespace log {

//class CAsyncLogger;
//using RAsyncLoggerSptr = std::shared_ptr<CAsyncLogger>;

/// @brief  异步日志类型
enum class EAsyncLogMessageType {
  kAsyncLogMessageType_Log,       ///< 日志
  kAsyncLogMessageType_Flush,     ///< 刷新
  kAsyncLogMessageType_Terminate, ///< 终止
};

/// @brief  异步日志信息
/// @note   只能移动不允许复制到队列中
struct SAsyncLogMessage
  : public CNocopyable
  , public CLogMessageBuffer {
  /// 默认构造函数
  SAsyncLogMessage() = default;
  /// @brief  构造函数
  /// @param  worker      异步记录器
  /// @param  async_type  异步消息类型
  /// @param  msg         异步消息
  SAsyncLogMessage(RAsyncLoggerSptr&& worker, EAsyncLogMessageType async_type, const SLogMessage& msg)
    : CLogMessageBuffer{msg}
    , msg_type{async_type}
    , worker_ptr{std::move(worker)} {
  }

  /// @brief  构造函数
  /// @param  worker      异步记录器
  /// @param  async_type  异步消息类型
  SAsyncLogMessage(RAsyncLoggerSptr&& worker, EAsyncLogMessageType async_type)
    : CLogMessageBuffer{}
    , msg_type{async_type}
    , worker_ptr{std::move(worker)} {
  }

  /// @brief  显示构造 委托函数
  /// @param  async_type  异步消息类型
  explicit SAsyncLogMessage(EAsyncLogMessageType async_type)
    : SAsyncLogMessage{nullptr, async_type} {
  }

  /// @brief  移动构造函数
  SAsyncLogMessage(SAsyncLogMessage&&) = default;
  /// @brief  移动赋值函数
  SAsyncLogMessage& operator=(SAsyncLogMessage&&) = default;

  EAsyncLogMessageType msg_type {EAsyncLogMessageType::kAsyncLogMessageType_Log}; ///< 异步日志类型
  RAsyncLoggerSptr worker_ptr {nullptr};  ///< 异步记录器
};

static const RSeconds kAsyncThreadPoolProcessMsgCd = RSeconds(10); ///< 线程池等待消息时间 10秒

/// @brief  异步线程池
class AFCORE_COMMON_API CAsyncThreadPool
  : public CNocopyable {
public:
  using RItemType = SAsyncLogMessage;
  using RMpmcType = CMpmcQueue<RItemType>;

  /// @brief  构造函数
  /// @param  q_max_items     消息最大容量
  /// @param  threads_n       线程池容量
  /// @param  on_thread_start 线程启动处理操作
  CAsyncThreadPool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start);
  /// @brief  构造函数
  /// @param  q_max_items     消息最大容量
  /// @param  threads_n       线程池容量
  CAsyncThreadPool(size_t q_max_items, size_t threads_n);

  /// @brief  析构函数
  ~CAsyncThreadPool();

  /// @brief  发送日志
  /// @param  worker_ptr      工作线程
  /// @param  msg             日志信息
  /// @param overflow_policy  溢出策略
  void PostLog(RAsyncLoggerSptr&& worker_ptr, const SLogMessage& msg, EAsyncOverflowPolicy overflow_policy);
  /// @brief  发送刷新
  /// @param  worker_ptr      工作线程
  /// @param overflow_policy  溢出策略
  void PostFlush(RAsyncLoggerSptr&& worker_ptr, EAsyncOverflowPolicy overflow_policy);
  /// @brief  获取当前累计越界的数量
  /// @return 当前累计越界的数量
  size_t GetOverrunCount();

private:
  /// @brief  线程池发送异步消息
  /// @param  new_msg             新的异步消息
  /// @param  overflow_policy     溢出策略
  void PostAsyncMsg(SAsyncLogMessage&& new_msg, EAsyncOverflowPolicy overflow_policy);
  /// @brief  线程池工作循环
  void WorkerLoop();
  /// @brief  线程池处理消息
  bool ProcessNextMsg();
private:
  RMpmcType q_;                       /// 多生产者多消费者队列
  std::vector<std::thread> threads_;  /// 线程容器
};

} // !namespace log

} // !namespace afcore

#endif //! AFCORE_COMMON_LOG_ASYNC_ASYNC_THREAD_POOL_